package com.hyper_yang.javase.fileAndIO;

import org.junit.jupiter.api.Test;

import java.io.*;

/*
对象流与序列化
    Java提供了一种对象序列化机制。用字节序列可以表示一个对象，该字节序列包含该对象的类型和对象中存储的属性等信息。
    字节序列写出到文件之后，相当于文件中持久保存了一个对象信息。反之，该字节序列还可以从文件中读取回来，重构对象，
    对他进行反序列化。对象的数据、对象的类型和对象中存储的数组信息，都可以用来在内存中创建对象。

对象字节流:
    对象输出节点流: 将程序中的对象存储到本地磁盘中    序列化
        ObjectOutputStream
    对象输入节点流: 将本地磁盘中的对象读取到程序中    反序列化
        ObjectInputStream
注意事项:
    1.NotSerializableException 不支持序列化异常
        需要序列化存储的对象的类必须实现 Serializable接口
    2.如果某些属性不想被序列化，在属性前 +
        static
        transient
    3.序列化(写出)和反序列化(读入)的 serialVersionUID要一致
        让 IDEA开发工具生成 serialVersionUID
 */
public class ObjIOTest {
    @Test
    public void test1() throws IOException {
        // 1.创建字节输出节点流
        FileOutputStream fos = new FileOutputStream("src\\main\\java\\com\\hyper_yang\\fileAndIO\\testFile\\obj.txt");
        // 2.对象输出节点流 (不具备传输数据的功能)
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        // 3.准备一个对象
        Person p = new Person("张三",18,3500.36,'男',"北京市");
        // 4.通过对象输出节点流，将 p对象写入到指定的文件里
        oos.writeObject(p);

        oos.close();
        fos.close();

        System.out.println("写出完毕");
    }

    @Test
    public void test2() throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream("src\\main\\java\\com\\hyper_yang\\fileAndIO\\testFile\\obj.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);

        Object o = ois.readObject();
        if (o instanceof Person p)
            System.out.println(p);
        System.out.println(o);


        ois.close();
        fis.close();
    }

}

class Person implements Serializable {
    @Serial
    private static final long serialVersionUID = -3396145052302891352L;
    String name;
    static Integer age;
    transient Double salary;
    Character gender;
    String country;

    public Person() {
    }

    public Person(String name, Integer age, Double salary, Character gender, String country) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.gender = gender;
        this.country = country;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                ", gender=" + gender +
                ", country='" + country + '\'' +
                '}';
    }
}